Skip to content

Make NativeAOT StressLog binary-compatible with CoreCLR#129300

Draft
max-charlamb wants to merge 1 commit into
dotnet:mainfrom
max-charlamb:maxcharlamb/nativeaot-stresslog-unify
Draft

Make NativeAOT StressLog binary-compatible with CoreCLR#129300
max-charlamb wants to merge 1 commit into
dotnet:mainfrom
max-charlamb:maxcharlamb/nativeaot-stresslog-unify

Conversation

@max-charlamb

Copy link
Copy Markdown
Member

Note

This PR was created with assistance from GitHub Copilot.

Summary

Align the NativeAOT StressLog struct layout to be binary-compatible with CoreCLR's, so that diagnostic tools reading raw memory (SOS !DumpLog, clrmd) can read stress logs from both runtimes without layout-specific code paths.

Motivation

The NativeAOT and CoreCLR StressLog structs were forked from the same file but diverged over time. While StressMsg, StressLogChunk, and ThreadStressLog remained compatible, the StressLog header class itself has different field ordering due to:

  • Lock type: CoreCLR uses CRITSEC_COOKIE (an 8-byte pointer). NativeAOT used minipal_mutex (40 bytes inline on Linux x64).
  • Missing padding sentinel: CoreCLR has unsigned padding = 0xFFFFFFFF between logs and deadCount.
  • Missing modules[] array: CoreCLR has a 5-entry ModuleDesc array for multi-module format string resolution.
  • LogMsg signature: CoreCLR passes (level, facility, ...), NativeAOT only passed (facility, ...).

These differences meant every field after logs was at a different offset, breaking raw-memory readers.

Changes

Lock type (stressLog.h, stressLog.cpp)

  • Changed from inline minipal_mutex to heap-allocated CrstStatic*
  • CrstStatic wraps the same minipal_mutex primitives, so runtime behavior is identical
  • In Debug builds, CrstStatic adds thread ownership assertions (strictly better)
  • Added null guard in CreateThreadStressLog for the unlikely allocation failure case

Struct layout (stressLog.h)

  • Added unsigned padding field (initialized to 0xFFFFFFFF) between logs and deadCount
  • Added ModuleDesc struct and modules[MAX_MODULES=5] array
  • Added static_asserts that verify all field offsets match the expected CoreCLR layout

API signatures (stressLog.h, stressLog.cpp)

  • Updated StressLog::LogMsg to (unsigned level, unsigned facility, int cArgs, const char* format, ...)
  • Updated STRESS_LOG_WRITE macro to pass level through to LogMsgOL
  • Updated LogMsgOL 2-arg overload to (unsigned facility, unsigned level, const char* format, Ts... args)
  • Updated all GC stress log macros (STRESS_LOG_PLUG_MOVE, STRESS_LOG_ROOT_PROMOTE, etc.) to pass the appropriate level

Related PRs

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Aligns the NativeAOT StressLog header layout and logging entrypoints toward CoreCLR compatibility so SOS / clrmd tooling can interpret stress log memory without runtime-specific parsing.

Changes:

  • Replaces the inline mutex with a pointer-sized heap-allocated CrstStatic* and updates locking in thread-log creation.
  • Adds CoreCLR-matching header fields (padding sentinel, ModuleDesc modules[5]) and initializes the module table.
  • Updates StressLog::LogMsg / STRESS_LOG_* plumbing to carry (level, facility, ...) in the signature.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.

File Description
src/coreclr/nativeaot/Runtime/stressLog.cpp Switches StressLog lock implementation to CrstStatic*, initializes module table, updates LogMsg signature.
src/coreclr/nativeaot/Runtime/inc/stressLog.h Updates macros and LogMsg signature; adds padding + modules[] fields and static_assert-based layout checks.
Comments suppressed due to low confidence (1)

src/coreclr/nativeaot/Runtime/stressLog.cpp:378

  • StressLog::LogMsg starts a va_list but returns early (pThread == NULL / msgs == 0) without calling va_end, and the new level parameter is unused. This is undefined behavior and can trigger -Werror unused-parameter builds.

Consider ensuring va_end is always reached and explicitly discarding level if it is intentionally not stored in the StressMsg payload.

void StressLog::LogMsg (unsigned level, unsigned facility, int cArgs, const char* format, ... )
{
    _ASSERTE ( cArgs >= 0 && (size_t)cArgs <= StressMsg::maxArgCnt );

    va_list Args;

Comment thread src/coreclr/nativeaot/Runtime/inc/stressLog.h
@dotnet-policy-service

Copy link
Copy Markdown
Contributor

Tagging subscribers to this area: @agocke, @dotnet/ilc-contrib
See info in area-owners.md if you want to be subscribed.

@max-charlamb max-charlamb force-pushed the maxcharlamb/nativeaot-stresslog-unify branch from 14b1ddd to 5da9202 Compare June 11, 2026 18:11
Align the NativeAOT StressLog struct layout to match CoreCLR's, so that
diagnostic tools reading raw memory (SOS !DumpLog, clrmd) can read
stress logs from both runtimes without layout-specific code paths.

Changes:
- Add padding field (0xFFFFFFFF sentinel) between logs and deadCount
- Change lock from inline minipal_mutex to heap-allocated CrstStatic*
  (pointer-sized, matching CoreCLR's CRITSEC_COOKIE)
- Add modules[MAX_MODULES=5] array with ModuleDesc struct
- Update StressLog::LogMsg signature to (level, facility, cArgs, fmt)
  matching CoreCLR's convention
- Update STRESS_LOG_WRITE macro and LogMsgOL overloads to pass level
- Add static_asserts verifying field offsets match CoreCLR layout
- Add null guard for lock in CreateThreadStressLog

The lock change uses CrstStatic which wraps the same minipal_mutex
primitives, so runtime behavior is identical. In Debug builds,
CrstStatic adds thread ownership assertions.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings June 11, 2026 19:01
@max-charlamb max-charlamb force-pushed the maxcharlamb/nativeaot-stresslog-unify branch from 5da9202 to e2d749d Compare June 11, 2026 19:01

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot encountered an error and was unable to review this pull request. You can try again by re-requesting a review.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants